package org.example.annotation.aspect;

import com.alibaba.fastjson.JSONObject;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.example.annotation.ResultAsJson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @description: 利用AOP进行自定义注解特殊操作
 * @author: cxu
 * @date: 2021/9/10 11:05
 */
@Aspect
@Component
public class ResultAsJsonHandler {
    private final Logger logger = LoggerFactory.getLogger(ResultAsJsonHandler.class);

    /**
     * @description: 定义切点
     */
    @Pointcut("@annotation(org.example.annotation.ResultAsJson)")
    public void pointcut() {
    }

    /**
     * @description: 利用切面编程打印信息
     * 如何获取注解的属性值？
     * pointcut = "pointcut() && @annotation(resultAsJson)" @annotation中的值应和方法中参数名一致
     * 方法中调用resultAsJson.value()即可获取注解属性值
     */
    @AfterReturning(pointcut = "pointcut() && @annotation(resultAsJson)", returning = "result")
    public void doAfterReturning(JoinPoint joinPoint, Object result, ResultAsJson resultAsJson) throws NoSuchMethodException {
        Signature signature = joinPoint.getSignature();
        String methodName = signature.getName();
        // 获取注解属性值 如本例中@ResultAsJson(value="XXX")获取XX
        // 方式一 结合@AfterReturning中引入@annotation(resultAsJson)，然后直接获取
        String description = resultAsJson.value();
        // 方式二 利用反射获取
        // 1. 获取目标类
        Class<?> clazz = joinPoint.getTarget().getClass();
        // 2. 获取所有参数类型
        Class[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        // 3. 获取目标方法
        Method method = clazz.getMethod(methodName, parameterTypes);
        // 4. 获取方法注解
        ResultAsJson annotation = method.getAnnotation(ResultAsJson.class);
        String descriptionTemp = annotation.value();

        logger.info("方法名:{}",methodName);
        logger.info(description + ":" + JSONObject.toJSON(result));
        logger.info(descriptionTemp + "-反射获取:" + JSONObject.toJSON(result));
    }
}
